package com.example.security.service.impl;

import com.example.security.dto.RoleDTO;
import com.example.security.entity.SysRole;
import com.example.security.mapper.RoleMapper;
import com.example.security.mapper.RolePermissionMapper;
import com.example.security.mapper.UserRoleMapper;
import com.example.security.service.RoleService;
import com.example.security.common.PageResult;
import com.example.security.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService {

    private final RoleMapper roleMapper;
    private final RolePermissionMapper rolePermissionMapper;
    private final UserRoleMapper userRoleMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    public PageResult<SysRole> getRolePage(int pageNum, int pageSize, SysRole query) {
        // 设置分页参数
        query.setPageNum(pageNum);
        query.setPageSize(pageSize);
        
        // 查询总数
        long total = roleMapper.selectCount(query);
        
        // 查询数据
        List<SysRole> list = roleMapper.selectPage(query);
        
        // 返回分页结果
        return PageResult.of(list, total, pageNum, pageSize);
    }

    @Override
    @Cacheable(value = "role", key = "'list'")
    public List<SysRole> getRoleList() {
        return roleMapper.selectList();
    }

    @Override
    @Cacheable(value = "role", key = "'permissions:' + #roleId")
    public List<Long> getRolePermissionIds(Long roleId) {
        return rolePermissionMapper.selectPermissionIdsByRoleId(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"role", "permission"}, allEntries = true)
    public void assignRolePermissions(Long roleId, List<Long> permissionIds) {
        // 删除原有权限
        rolePermissionMapper.deleteByRoleId(roleId);
        
        // 分配新权限
        if (!CollectionUtils.isEmpty(permissionIds)) {
            rolePermissionMapper.batchInsert(roleId, permissionIds);
        }
        
        // 获取该角色下的所有用户ID
        List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(roleId);
        
        // 清除这些用户的权限缓存
        userIds.forEach(userId -> {
            redisTemplate.delete("permission:user:" + userId);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "role", allEntries = true)
    public void addRole(SysRole role) {
        // 检查角色编码是否存在
        if (roleMapper.selectByCode(role.getRoleCode()) != null) {
            throw new BusinessException("角色编码已存在");
        }
        
        role.setCreateTime(LocalDateTime.now());
        roleMapper.insert(role);
        
        // 分配权限
        if (!CollectionUtils.isEmpty(role.getPermissionIds())) {
            rolePermissionMapper.batchInsert(role.getId(), role.getPermissionIds());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "role", allEntries = true)
    public void updateRole(SysRole role) {
        // 检查角色编码是否存在
        SysRole existingRole = roleMapper.selectByCode(role.getRoleCode());
        if (existingRole != null && !existingRole.getId().equals(role.getId())) {
            throw new BusinessException("角色编码已存在");
        }
        
        role.setUpdateTime(LocalDateTime.now());
        roleMapper.update(role);
        
        // 更新权限
        rolePermissionMapper.deleteByRoleId(role.getId());
        if (!CollectionUtils.isEmpty(role.getPermissionIds())) {
            rolePermissionMapper.batchInsert(role.getId(), role.getPermissionIds());
        }
        
        // 清除相关用户的权限缓存
        List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(role.getId());
        userIds.forEach(userId -> {
            redisTemplate.delete("permission:user:" + userId);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"role", "permission"}, allEntries = true)
    public void deleteRole(Long roleId) {
        // 检查是否有用户关联此角色
        List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(roleId);
        if (!CollectionUtils.isEmpty(userIds)) {
            throw new BusinessException("该角色下存在用户，无法删除");
        }
        
        // 删除角色权限关联
        rolePermissionMapper.deleteByRoleId(roleId);
        // 删除角色
        roleMapper.deleteById(roleId);
    }

    @Override
    public List<SysRole> getAllRoles() {
        return roleMapper.selectAll();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysRole createRole(RoleDTO roleDTO) {
        // 检查角色编码是否存在
        if (roleMapper.selectByCode(roleDTO.getRoleCode()) != null) {
            throw new BusinessException("角色编码已存在");
        }

        SysRole role = new SysRole();
        BeanUtils.copyProperties(roleDTO, role);
        role.setCreateTime(LocalDateTime.now());
        roleMapper.insert(role);
        return role;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysRole updateRole(Long roleId, RoleDTO roleDTO) {
        // 检查角色是否存在
        SysRole existRole = roleMapper.selectById(roleId);
        if (existRole == null) {
            throw new BusinessException("角色不存在");
        }

        // 检查角色编码是否重复
        SysRole roleWithCode = roleMapper.selectByCode(roleDTO.getRoleCode());
        if (roleWithCode != null && !roleWithCode.getId().equals(roleId)) {
            throw new BusinessException("角色编码已存在");
        }

        BeanUtils.copyProperties(roleDTO, existRole);
        existRole.setUpdateTime(LocalDateTime.now());
        roleMapper.update(existRole);
        return existRole;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignPermissions(Long roleId, List<Long> permissionIds) {
        // 检查角色是否存在
        if (roleMapper.selectById(roleId) == null) {
            throw new BusinessException("角色不存在");
        }

        // 删除原有权限
        rolePermissionMapper.deleteByRoleId(roleId);
        
        // 分配新权限
        if (!permissionIds.isEmpty()) {
            rolePermissionMapper.batchInsert(roleId, permissionIds);
        }
    }

    @Override
    public List<String> getUserRoleCodes(Long userId) {
        List<SysRole> roles = roleMapper.selectByUserId(userId);
        if (!roles.isEmpty()) {
            return roles.stream().map(SysRole::getRoleCode).collect(Collectors.toList());
        }
        return null;
    }
} 